﻿//========================================================= 
/**@file LC_SM2CipherFactoryCmdDriver.h
 * @brief 以SM2算法根据公私对产生通信密钥的驱动
 * 
 * @date 2017-10-25   22:12:59
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_LC_SM2CIPHERADAPTERCMDDRIVER_H_
#define _LIBZHOUYB_LC_SM2CIPHERADAPTERCMDDRIVER_H_
//--------------------------------------------------------- 
#include "../CommonCmdDriver.h"

#include "LC_FileCipherFactoryCmdDriver.h"

#include "../../../extension/security/openssl/SM2_Provider.h"
using zhou_yb::extension::security::SM2_Provider;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
//--------------------------------------------------------- 
/**
 * @brief 公私钥对产生过程密钥的密码器
 * @date 2017-10-25 22:15:05
 */
class LC_SM2CipherAdapterCmdDriver : 
    public CommonCmdDriver,
    public BaseDevAdapterBehavior<FileVirtualCipher>
{
protected:
    /// 私钥
    ByteBuilder _dB;
    /// 解密数据
    bool _DecryptKEY(IStringArguments& arg, const char* key, ByteBuilder& data)
    {
        if(_dB.IsEmpty())
        {
            _logErr(DeviceError::DevInitErr, "私钥为空");
            return false;
        }
        string sID = key;
        string sData = arg[sID].To<string>();

        ByteBuilder buff(16);
        DevCommand::FromAscii(sData.c_str(), buff);
        if(buff.IsEmpty())
        {
            sID += "字段为空";
            _logErr(DeviceError::ArgIsNullErr, sID.c_str());
            return false;
        }
        SM2_Provider sm2 = SM2_Provider::Default();
        if(!sm2.Decrypt(buff, _dB, data))
        {
            _logErr(DeviceError::OperatorErr, "SM2解密数据失败");
            return false;
        }
        return true;
    }
public:
    LC_SM2CipherAdapterCmdDriver() : CommonCmdDriver()
    {
        _RegisteCMD(LC_SM2CipherAdapterCmdDriver, GenKEY);
        _RegisteCMD(LC_SM2CipherAdapterCmdDriver, CipherKEY);
        _RegisteCMD(LC_SM2CipherAdapterCmdDriver, DecryptKEY);

        _RegisteAdapterCMD(LC_SM2CipherAdapterCmdDriver);
    }
    LC_CMD_ADAPTER_THIS(FileVirtualCipher);
    /**
     * @brief 产生公钥和随机数
     * @date 2017-10-25 22:19
     *
     * @retval XB : hex 公钥X
     * @retval YB : hex 公钥Y
     * @retval Random : hex 产生通讯密钥的16位随机数密文
     * @retval KCV : hex 随机数SM4的KCV
     */
    LC_CMD_METHOD(GenKEY)
    {
        SM2_Provider sm2 = SM2_Provider::Default();
        _dB.Clear();

        ByteBuilder xB(32);
        ByteBuilder yB(32);
        if(!sm2.GenKEY(xB, yB, _dB))
            return false;
        ByteBuilder buff(32);
        ByteConvert::ToAscii(xB, buff);
        rlt.Put("XB", buff.GetString());
        buff.Clear();
        ByteConvert::ToAscii(yB, buff);
        rlt.Put("YB", buff.GetString());

        ByteBuilder randomK(32);
        openssl_helper::Random(randomK, 32);

        ByteBuilder data(16);
        openssl_helper::Random(data, 16);

        buff.Clear();
        if(!sm2.Encrypt(randomK, xB, yB, data, buff))
        {
            _logErr(DeviceError::OperatorErr, "SM2加密数据失败");
            return false;
        }
        data.Clear();

        ByteConvert::ToAscii(buff, data);
        rlt.Put("Random", data.GetString());
        return true;
    }
    /**
     * @brief 初始化密码器工作密钥
     * @date 2017-10-25 22:22:31
     *
     * @param [in] Random : hex 加密后的16位随机数(分散因子)
     * @param [in] KCV : hex [default:Null] 随机数SM4的KCV
     * @param [in] MkIndex : byte [default:0x00] 需要产生的主密钥序号
     * @param [in] MIN : byte [default:0x00] 需要产生的最小密钥索引
     * @param [in] MAX : byte [default:0xFF] 需要产生的最大密钥索引
     */
    LC_CMD_METHOD(CipherKEY)
    {
        ASSERT_FuncErrInfo(!_pDev.IsNull(), DeviceError::ArgIsNullErr, "适配的设备为空");

        ByteBuilder data(32);
        if(!_DecryptKEY(arg, "Random", data))
            return false;

        ByteBuilder buff(32);
        ByteBuilder tmp(32);
        byte kMin = arg["MIN"].To<byte>(0x00);
        byte kMax = arg["MAX"].To<byte>(0x0FF);
        uint mkIndex = arg["MkIndex"].To<uint>(0x00);
        for(uint i = kMin;i <= kMax; ++i)
        {
            tmp.Clear();
            buff.Clear();
            buff.Append(static_cast<byte>(i), 16);

            SM4_Provider::ECB_Encrypt(buff, data, tmp);
            if(!_pDev->DownloadWK(mkIndex, i, tmp))
            {
                string errMsg = "下载密钥[";
                errMsg += ArgConvert::ToString(mkIndex);
                errMsg += ",";
                errMsg += ArgConvert::ToString(i);
                errMsg += "]失败";
                _logErr(DeviceError::OperatorErr, errMsg.c_str());
                return false;
            }
        }
        return true;
    }
    /**
     * @brief 私钥解密
     * @date 2017-10-30 14:38
     * @param [in] Key : hex 需要用私钥解密的数据(使用公钥加密)
     *
     * @retval Key : hex 解密后的密钥数据
     */
    LC_CMD_METHOD(DecryptKEY)
    {
        ByteBuilder data(32);
        if(!_DecryptKEY(arg, "Key", data))
            return false;
        ByteBuilder buff(32);
        ByteConvert::ToAscii(data, buff);
        rlt.Put("Key", buff.GetString());
        return true;
    }
};
//--------------------------------------------------------- 
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_LC_SM2CIPHERADAPTERCMDDRIVER_H_
//========================================================= 